package cn.vic.genertor.view;

import cn.vic.config.Configuration;
import cn.vic.config.GenertorConfig;
import cn.vic.config.HistoricalRecord;
import cn.vic.config.TypeMapping;
import cn.vic.config.model.DatabaseElement;
import cn.vic.db.Database;
import cn.vic.db.DatabaseFactory;
import cn.vic.db.model.Table;
import cn.vic.genertor.engine.FreeMarkrTemplate;
import cn.vic.genertor.engine.GenerateInterface;
import cn.vic.genertor.view.ui.TreeNodeData;
import cn.vic.model.RepidModel;
import cn.vic.util.FileUtil;
import cn.vic.util.StringUtil;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.TimerTask;
import java.util.concurrent.*;

/**
 * @author vic
 */
public class LoadAotuCodeView extends JDialog {
    /**
     * 线程池
     */
    private ExecutorService NEW_FIXED_THREAD_POOL;
    /**
     *
     */
    private CompletionService<Table> completionService;
    /**
     * 多个表集合
     */
    private java.util.List<Table> tableModels = new ArrayList<>();
    /**
     * 配置信息
     */
    private Configuration configuration;
    /**
     * 表名
     */
    private String tableNames;
    /**
     * 选中的tree列表
     */
    private TreePath[] selectionPaths;
    /**
     * sql 对应 java 的配置信息
     */
    private TypeMapping typeMapping;

    /**
     * 生成
     * new {@link FreeMarkrTemplate}
     */
    private GenerateInterface generate = new FreeMarkrTemplate();
    /**
     * 历史记录
     */
    private HistoricalRecord historicalRecord = new HistoricalRecord();


    public LoadAotuCodeView(Frame parent, boolean m) {
        super(parent, m);
        initComponents();
        this.setLocationRelativeTo(parent);
    }

    /**
     * Creates new form LoadAotuCodeView
     */
    public LoadAotuCodeView(Frame parent, Configuration configuration, Table... tableModels) {
        super(parent, true);
        this.tableModels.addAll(Arrays.asList(tableModels));
        StringBuffer tableName = new StringBuffer();
        for (Table tableModel : tableModels) {
            tableName.append(tableModel.getTableName()).append(";");
        }
        init(parent, configuration, tableName.toString());
    }

    public LoadAotuCodeView(Frame parent, Configuration configuration, String tableNames) {
        super(parent, true);
        init(parent, configuration, tableNames);
    }

    /**
     * 初始化 方法
     *
     * @param parent
     * @param configuration
     * @param tableNames
     */
    private void init(Frame parent, Configuration configuration, String tableNames) {
        //初始化view 配置
        initComponents();
        int x = parent.getX() + parent.getWidth() / 2 - this.getWidth() / 2;
        int y = parent.getY() + parent.getHeight() / 2 - this.getHeight() / 2;
        this.setBounds(x, y, 389, 330);

        historicalRecord.loadGenertorConfig();
        this.configuration = configuration;
        this.tableNames = tableNames;
        NEW_FIXED_THREAD_POOL = Executors.newFixedThreadPool(Integer.valueOf(configuration.getOutThreadNum()));
        completionService = new ExecutorCompletionService<>(NEW_FIXED_THREAD_POOL);
        textHandle();
    }

    /**
     * 给文本进行赋值
     */
    public void textHandle() {
        jTextField1.setText(tableNames);//表名
        GenertorConfig genertorConfig = historicalRecord.getNewestConfig();
        if (genertorConfig != null) {
            jTextField5.setText(genertorConfig.getModular());
            jTextField6.setText(genertorConfig.getCustomParam());

            jTextField2.setText(genertorConfig.getBasePackage());
            jTextField3.setText(genertorConfig.getTemplatePath());
            jTextField4.setText(genertorConfig.getOutputPath());
        }


        Dimension dimension = jTextField2.getSize();
        dimension.setSize(180, dimension.getHeight());
        jTextField1.setPreferredSize(dimension);
        jTextField2.setPreferredSize(dimension);
        jTextField3.setPreferredSize(dimension);
        jTextField4.setPreferredSize(dimension);
    }


    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    private void initComponents() {
        setTitle("生成配置");
        setResizable(false);
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jTextField2 = new javax.swing.JTextField();
        jTextField3 = new javax.swing.JTextField();
        jTextField4 = new javax.swing.JTextField();
        jTextField5 = new javax.swing.JTextField();
        jTextField6 = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jProgressBar = new javax.swing.JProgressBar();
        jProgressBar.setStringPainted(true);
        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jLabel1.setText("表名");
        jTextField1.setEnabled(false);
        jLabel2.setText("Package");
        jLabel5.setText("模块");
        jLabel6.setText("自定义参数(Json)");
        jLabel3.setText("模版路径");
        jLabel4.setText("保存路径");

        jButton1.setText("生成");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("取消");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                doClose();
            }
        });

        jButton3.setText("浏览");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jButton4.setText("浏览");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addGroup(layout.createSequentialGroup()
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                                                        .addComponent(jLabel4)
                                                                        .addComponent(jLabel3))
                                                                .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING)
                                                                .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.TRAILING)
                                                                .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING)
                                                        )
                                                        .addComponent(jLabel1))
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                                        .addComponent(jTextField2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE)
                                                        .addComponent(jTextField5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE)
                                                        .addComponent(jTextField6, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE)
                                                        .addComponent(jTextField3, javax.swing.GroupLayout.Alignment.LEADING)
                                                        .addComponent(jTextField4)
                                                        .addComponent(jTextField1, javax.swing.GroupLayout.Alignment.LEADING))
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                        .addComponent(jButton3)
                                                        .addComponent(jButton4))
                                                .addGap(0, 0, Short.MAX_VALUE))
                                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                .addComponent(jProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                .addGap(18, 18, 18)
                                                .addComponent(jButton2)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(jButton1)))
                                .addContainerGap())
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addGap(16, 16, 16)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(jLabel1)
                                        .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(jLabel2)
                                        .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(jLabel5)
                                        .addComponent(jTextField5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(jLabel6)
                                        .addComponent(jTextField6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(jLabel3)
                                        .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(jButton3))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jLabel4)
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                                .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addComponent(jButton4)))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                                .addComponent(jButton1)
                                                .addComponent(jButton2))
                                        .addComponent(jProgressBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addContainerGap())
        );

        pack();
    }

    /**
     * 生成代码
     *
     * @param evt
     */
    private void jButton1ActionPerformed(ActionEvent evt) {
        GenertorConfig genertorConfig = getViewParam();
        if (genertorConfig == null) {
            return;
        }
        /**
         * 生成处理方法
         * 处理数据
         */
        new Thread(new Runnable() {
            @Override
            public void run() {
                genertorAlsoCloseView();
            }
        }).start();

    }

    private GenertorConfig getViewParam() {
        GenertorConfig genertorConfig = new GenertorConfig();
        genertorConfig.setBasePackage(jTextField2.getText());
        genertorConfig.setModular(jTextField5.getText());
        genertorConfig.setCustomParam(jTextField6.getText());
        genertorConfig.setTemplatePath(jTextField3.getText());
        genertorConfig.setOutputPath(jTextField4.getText());

        if (StringUtil.isEmpty(genertorConfig.getBasePackage())) {
            JOptionPane.showMessageDialog(this, "请输入 包名.", "提示", JOptionPane.INFORMATION_MESSAGE);
            return null;
        }
        if (StringUtil.isEmpty(genertorConfig.getTemplatePath())) {
            JOptionPane.showMessageDialog(this, "请选择 模版路径.", "提示", JOptionPane.INFORMATION_MESSAGE);
            return null;
        }
        if (StringUtil.isEmpty(genertorConfig.getOutputPath())) {
            JOptionPane.showMessageDialog(this, "请选择 保存路径", "提示", JOptionPane.INFORMATION_MESSAGE);
            return null;
        }

        return genertorConfig;
    }

    /**
     * 异步调用生成方法
     * 并且关闭窗口
     */
    private void genertorAlsoCloseView() {

        GenertorConfig genertorConfig = getViewParam();
        if (genertorConfig == null) {
            return;
        }
        historicalRecord.addRecord(genertorConfig);
        historicalRecord.save();
        //判断是否多选，或者多条数据
        if (selectionPaths != null && selectionPaths.length > 0) {
            //使用多线程获取表信息
            threadGetTableGenertor(genertorConfig);
        } else {
            //有table对象信息
            singleTableGenertor(genertorConfig);
        }
        //200毫秒关闭窗口
        java.util.Timer timers = new java.util.Timer();
        timers.schedule(new TimerTask() {
            @Override
            public void run() {
                doClose();
            }
        }, 200);

    }

    /**
     * 单个表 处理
     * 不使用线程处理
     */
    private void singleTableGenertor(GenertorConfig config) {

        jProgressBar.setValue(30);
        RepidModel model = new RepidModel();
        model.setTableName("");
        model.setPackages(config.getBasePackage());
        model.setModule(config.getModular());
        model.addCustomParam(config.getCustomParam());
        model.setTemplatePath(FileUtil.getFilePathByRun(config.getTemplatePath()));
        model.setSavePath(FileUtil.getFilePathByRun(config.getOutputPath()));
        model.setTableModels(tableModels);
        jProgressBar.setValue(70);

        generate.setHasOpen(true);
        generate.processToFile(model);
        jProgressBar.setValue(100);
        jProgressBar.setString("处理完成");
    }

    /**
     * 多线程处理 获取表信息
     */
    public void threadGetTableGenertor(GenertorConfig config) {
        if (selectionPaths == null || selectionPaths.length == 0 || typeMapping == null) {
            return;
        }

        for (TreePath treePath : selectionPaths) {
            completionService.submit(new GetLoaderTable(treePath, typeMapping));
        }
        int count = selectionPaths.length;
        //jProgressBar自带最小值。自动调整显示百分比
        //jProgressBar.setMaximum(count);
        for (int i = 0; i < count; i++) {
            try {
                Future<Table> future = completionService.take();
                Table table = future.get();

                RepidModel model = new RepidModel();
                model.setTableName("");
                model.setPackages(config.getBasePackage());
                model.setModule(config.getModular());
                model.addCustomParam(config.getCustomParam());
                model.setTemplatePath(FileUtil.getFilePathByRun(config.getTemplatePath()));
                model.setSavePath(FileUtil.getFilePathByRun(config.getOutputPath()));
                model.setTableModels(table);

                if (i + 1 == count) {
                    generate.setHasOpen(true);
                }
                generate.processToFile(model);


                double num = 100d / count * (i + 1);
                System.err.println(num + " >>> " + new Double(Math.floor(num)).intValue());
                jProgressBar.setValue(new Double(Math.floor(num)).intValue());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        jProgressBar.setString("处理完成");
    }


    /**
     * 线程获取table对象
     */
    private class GetLoaderTable implements Callable<Table> {

        private TreePath treePath;
        private TypeMapping typeMapping;

        GetLoaderTable(TreePath treePath, TypeMapping typeMapping) {
            this.treePath = treePath;
            this.typeMapping = typeMapping;
        }

        @Override
        public Table call() throws SQLException {
            Connection connection = null;
            try {
                DefaultMutableTreeNode mutableTreeNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();
                TreeNodeData treeNodeData1 = (TreeNodeData) mutableTreeNode.getUserObject();
                DatabaseElement databaseElement = treeNodeData1.getDatabaseElement();
                connection = databaseElement.getConnection(treeNodeData1.getDataBase());
                Database db = DatabaseFactory.createDatabase(connection, typeMapping);
                String nodeText = treeNodeData1.getText();
                String tableSchema = null;
                String tableName = nodeText;
                if (nodeText.indexOf(".") > 0) {
                    tableName = nodeText.substring(nodeText.indexOf(".") + 1);
                    tableSchema = nodeText.substring(0, nodeText.indexOf("."));
                }
                Table table = db.getTable(null, tableSchema, tableName);
                return table;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.isReadOnly();
                }
            }
            return null;
        }
    }


    /**
     * 显示文件
     *
     * @param jTextField
     */
    private void showFilePanle(JTextField jTextField) {
        JFileChooser jFileChooser1 = new JFileChooser();
        //设置打开路径
        String path = FileUtil.getFilePathByRun(jTextField.getText());
        jFileChooser1.setCurrentDirectory(new File(path));
        jFileChooser1.setMultiSelectionEnabled(false);
        jFileChooser1.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        int result = jFileChooser1.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = jFileChooser1.getSelectedFile();
            String filepath = file.getAbsolutePath();
            // 将文件路径设到JTextField
            jTextField.setText(FileUtil.getFilePathBySave(filepath));
        }
    }

    public void setSelectionPaths(TreePath[] selectionPaths) {
        this.selectionPaths = selectionPaths;
    }

    private void jButton4ActionPerformed(ActionEvent evt) {
        showFilePanle(jTextField4);
    }

    private void jButton3ActionPerformed(ActionEvent evt) {
        showFilePanle(jTextField3);
    }

    public void setTypeMapping(TypeMapping typeMapping) {
        this.typeMapping = typeMapping;
    }

    public GenerateInterface getGenerate() {
        return generate;
    }

    public void setGenerate(GenerateInterface generate) {
        this.generate = generate;
    }


    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                LoadAotuCodeView dialog = new LoadAotuCodeView(new JFrame(), true);
                dialog.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
            }
        });
    }

    private void doClose() {
        setVisible(false);
        dispose();
    }

    // Variables declaration - do not modify
    private JButton jButton1;
    private JButton jButton2;
    private JButton jButton3;
    private JButton jButton4;
    private JLabel jLabel1;
    private JLabel jLabel2;
    private JLabel jLabel3;
    private JLabel jLabel4;
    private JLabel jLabel5;
    private JLabel jLabel6;
    private JProgressBar jProgressBar;
    private JTextField jTextField1;
    private JTextField jTextField2;
    private JTextField jTextField3;
    private JTextField jTextField4;
    private JTextField jTextField5;
    private JTextField jTextField6;
    // End of variables declaration

}
